home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
- static char rcsid[] = "$Header: gram.c,v 2.5 85/08/22 16:03:16 timo Exp $";
-
- /*
- * B editor -- All routines referencing the grammar table are in this file.
- */
-
- #include "b.h"
- #include "feat.h"
- #include "bobj.h"
- #include "node.h"
- #include "gram.h"
- #include "supr.h"
- #include "tabl.h"
-
- extern bool dflag;
-
- #include <ctype.h>
-
-
- /*
- * Test whether sym is in the given class.
- */
-
- Visible bool
- isinclass(sym, ci)
- register int sym;
- struct classinfo *ci;
- {
- register classptr cp;
-
- Assert(ci && ci->c_class);
- if (sym == Hole)
- return !isinclass(Optional, ci);
- for (cp = ci->c_class; *cp; ++cp)
- if (sym == *cp)
- return Yes;
- return No;
- }
-
-
- /*
- * Deliver the representation array for the given node.
- * If the node is actually just a "text" value, construct
- * one in static storage -- which is overwritten at each call.
- * In this case there are two deficiencies: the next call to
- * noderepr which uses the same feature overwrites the reply
- * value of the previous call, AND if the text value itself
- * is changed, the representation may change, too.
- * In practical use this is no problem at all, however.
- */
-
- Visible string *
- noderepr(n)
- register node n;
- {
- register int sym;
-
- if (n && Type(n) == Tex) {
- static string buf[2];
- buf[0] = Str((value)n);
- return buf;
- }
- sym = symbol(n);
- return table[sym].r_repr;
- }
-
-
- /*
- * Deliver the prototype node for the given symbol.
- */
-
- Visible node
- gram(sym)
- register int sym;
- {
- Assert(sym == 0 || sym > 0 && sym < TABLEN && table[sym].r_symbol);
- return table[sym].r_node;
- }
-
- #ifdef SAVEBUF
-
- /*
- * Deliver the name of a symbol.
- */
-
- Visible string
- symname(sym)
- int sym;
- {
- static char buf[20];
-
- if (sym >= 0 && sym < TABLEN && table[sym].r_name)
- return table[sym].r_name;
- sprintf(buf, "%d", sym);
- return buf;
- }
-
-
- /*
- * Find the symbol corresponding to a given name.
- * Return -1 if not found.
- */
-
- Visible int
- nametosym(str)
- register string str;
- {
- register int sym;
- register string name;
-
- for (sym = 0; sym < TABLEN; ++sym) {
- name = table[sym].r_name;
- if (name && Strequ(name, str))
- return sym;
- }
- return -1;
- }
-
- #endif SAVEBUF
-
- /*
- * Test whether `sym' may replace the node in the path `p'.
- */
-
- Visible bool
- allowed(p, sym)
- register path p;
- register int sym;
- {
- register path pa = parent(p);
- register int ich = ichild(p);
- register int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
-
- Assert(sympa >= 0 && sympa < TABLEN && ich > 0 && ich <= MAXCHILD);
- return isinclass(sym, table[sympa].r_class[ich-1]);
- }
-
-
- /*
- * Initialize (and verify) the grammar table.
- */
-
- Visible Procedure
- initgram()
- {
- register int sym;
- register int nch;
- register struct classinfo **cp;
- register struct classinfo *sp;
- node ch[MAXCHILD];
-
- #ifndef NDEBUG
- if (dflag)
- fprintf(stderr, "*** initgram();\n\r");
- #endif NDEBUG
- /* Set the node pointers in the table and check the representations.
- The code assumes Optional and Hole are the last
- symbols in the table, i.e. the first processed by the loop. */
-
- for (sym = TABLEN-1; sym >= 0; --sym) {
- if (table[sym].r_symbol != sym) {
- if (sym != Hole && sym != Optional && table[sym].r_symbol == 0)
- continue; /* Disabled table entry */
- syserr("initgram: table order (%s=%d, should be %d)",
- table[sym].r_name, table[sym].r_symbol, sym);
- }
- cp = table[sym].r_class;
- for (nch = 0; nch < MAXCHILD && (sp = cp[nch]); ++nch)
- ch[nch] =
- table[sp->c_class[0] == Optional ?
- Optional : Hole].r_node;
- table[sym].r_node = newnode(nch, sym, ch);
- fix((value) table[sym].r_node);
- }
-
- initcodes();
- #ifdef USERSUGG
- initclasses();
- #endif USERSUGG
- }
-
-
- #ifdef USERSUGG
-
- /*
- * Add built-in commands to the suggestion tables.
- */
-
- Hidden Procedure
- initclasses()
- {
- register int i;
- register int j;
- register struct table *tp;
-
- for (i = 0; i < TABLEN; ++i) {
- tp = &table[i];
- if (tp->r_symbol != i || i == Suggestion)
- continue; /* Dead entry */
- for (j = 0; j < MAXCHILD && tp->r_class[j]; ++j) {
- if (isinclass(Suggestion, tp->r_class[j]))
- makesugg(tp->r_class[j]->c_class);
- }
- }
- }
-
-
- /*
- * Extract suggestions from class list.
- */
-
- Hidden Procedure
- makesugg(cp)
- classptr cp;
- {
- struct table *tp;
- string *rp;
- char buffer[1000];
- string bp;
- string sp;
- int i;
- int nch;
-
- for (; *cp; ++cp) {
- if (*cp >= TABLEN || *cp < 0)
- continue;
- tp = &table[*cp];
- rp = tp->r_repr;
- if (rp[0] && isupper(rp[0][0])) {
- bp = buffer;
- nch = nchildren(tp->r_node);
- for (i = 0; i <= nch; ++i) {
- if (rp[i]) {
- for (sp = rp[i]; *sp >= ' '; ++sp)
- *bp++ = *sp;
- }
- if (i < nch && !isinclass(Optional, tp->r_class[i]))
- *bp++ = '?';
- }
- if (bp > buffer) {
- *bp = 0;
- addsugg(buffer, Yes);
- }
- }
- }
- }
-
- #endif USERSUGG
-
-
- /*
- * Compaction scheme for characters to save space in grammar tables
- * by combining characters with similar properties (digits, l.c. letters).
- */
-
- #define RANGE 128 /* ASCII characters are in {0 .. RANGE-1} */
-
- Visible char code_array[RANGE];
- Visible char invcode_array[RANGE];
- Visible int lastcode;
-
- Hidden Procedure
- initcodes()
- {
- register int c;
-
- code_array['\n'] = ++lastcode;
- invcode_array[lastcode] = '\n';
- for (c = ' '; c <= '0'; ++c) {
- code_array[c] = ++lastcode;
- invcode_array[lastcode] = c;
- }
- for (; c <= '9'; ++c)
- code_array[c] = lastcode;
- for (; c <= 'a'; ++c) {
- code_array[c] = ++lastcode;
- invcode_array[lastcode] = c;
- }
- for (; c <= 'z'; ++c)
- code_array[c] = lastcode;
- for (; c < RANGE; ++c) {
- code_array[c] = ++lastcode;
- invcode_array[lastcode] = c;
- }
- }
-
-
- /*
- * Set the root of the grammar to the given symbol. It must exist.
- */
-
- Visible Procedure
- setroot(name)
- string name;
- {
- register int k;
- register int i;
-
- for (k = 1; k < TABLEN; ++k) {
- if (table[k].r_name && Strequ(name, table[k].r_name)) {
- table[Rootsymbol].r_symbol = table[k].r_symbol;
- table[Rootsymbol].r_name = table[k].r_name;
- for (i = 0; i < MAXCHILD; ++i) {
- table[Rootsymbol].r_repr[i] = table[k].r_repr[i];
- table[Rootsymbol].r_class[i] = table[k].r_class[i];
- }
- table[Rootsymbol].r_repr[i] = table[k].r_repr[i];
- table[Rootsymbol].r_node = table[k].r_node;
- table[Rootsymbol].r_symbol = Rootsymbol;
- return;
- }
- }
- syserr("Can't set root of grammar to <%s>", name);
- }
-
-
- /*
- * The remainder of this file is specific for the currently used grammar.
- */
-
-
- #include "boot.h" /* Has static data, so should be included only once! */
- #include "syms.h"
-
- Visible struct table *table = b_grammar;
-
-
- /*
- * Table indicating which symbols are used to form lists of items.
- * Consulted via predicate 'issublist' in "gram.c".
- */
-
- Hidden classelem Asublists[] = {
- E_plus, F_e_plus,
- And, And_kw, Or, Or_kw,
- 0,
- };
-
- Hidden struct classinfo sublists[] = {Asublists};
-
-
- /*
- * Predicate telling whether two symbols can form lists together.
- * This is important for list whose elements must alternate in some
- * way, as is the case for [KEYWORD [expression] ]*.
- *
- * This code must be in this file, otherwise the names and values
- * of the symbols would have to be made public.
- */
-
- Visible bool
- samelevel(sym, sym1)
- register int sym;
- register int sym1;
- {
- register int zzz;
-
- if (sym1 == sym)
- return Yes;
- if (sym1 < sym)
- zzz = sym, sym = sym1, sym1 = zzz; /* Ensure sym <= sym1 */
- /* Now always sym < sym1 */
- return sym == Kw_plus && sym1 == E_plus
- || sym == F_kw_plus && sym1 == F_e_plus
- || sym == And && sym1 == And_kw
- || sym == Or && sym1 == Or_kw;
- }
-
-
- /*
- * Predicate to tell whether a symbol can form chained lists.
- * By definition, all right-recursive symbols can do so;
- * in addition, those listed in the class 'sublists' can do
- * it, too (this is used for lists formed of alternating members
- * such as KW expr KW ...).
- */
-
- Visible bool
- issublist(sym)
- register int sym;
- {
- register int i;
- register string repr;
-
- Assert(sym < TABLEN);
- if (isinclass(sym, sublists))
- return Yes;
- repr = table[sym].r_repr[0];
- if (Fw_positive(repr))
- return No;
- for (i = 0; i < MAXCHILD && table[sym].r_class[i]; ++i)
- ;
- if (i <= 0)
- return No;
- repr = table[sym].r_repr[i];
- if (!Fw_zero(repr))
- return No;
- return isinclass(sym, table[sym].r_class[i-1]);
- }
-